﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Kinect.Toolbox;
using Microsoft.Kinect;
using MayhemCore;

namespace KinectModule.KinectHelpers
{
    public class KinectManager
    {
        private KinectSensor _sensor;
        private SwipeGestureDetector _gestureDetector;
        private MotionType _motionType;
        private Skeleton _body;

        private Action _trigger { get; set; }

        public bool IsTracked { get; set; }

        public KinectManager()
        {
            _gestureDetector = new SwipeGestureDetector();

            // On se branche sur le manager des sensors
            KinectSensor.KinectSensors.StatusChanged += new EventHandler<StatusChangedEventArgs>(KinectSensors_StatusChanged);

            // Si il y en a déjà un, on l'ouvre
            if (KinectSensor.KinectSensors.Count > 0)
            {
                this.OpenKinect(KinectSensor.KinectSensors.First());
            }

            _gestureDetector.OnGestureDetected += new Action<string>(gestureDetector_OnGestureDetected);
        }

        void KinectSensors_StatusChanged(object sender, StatusChangedEventArgs e)
        {
            if (e.Status == KinectStatus.Connected)
            {
                OpenKinect(e.Sensor);
            }
            else if (e.Status == KinectStatus.Disconnected)
            {
                _sensor = null;
            }
        }

        private void OpenKinect(KinectSensor kinectSensor)
        {
            _sensor = kinectSensor;
        }

        public void StartKinect()
        {
            _sensor.Start();
        }

        public void StopKinect()
        {
            _sensor.Stop();
        }

        public void RemoveHandler()
        {
            _sensor.Stop();
        }

        public void AddHandler(MotionType motionType, Action action)
        {
            _motionType = motionType;
            _trigger = action;
            try
            {
                ConfigureKinect();
            }
            catch (Exception)
            {
                ErrorLog.AddError(ErrorType.Failure, "Kinect's device not found");
            }
        }

        public void ConfigureKinect()
        {
            StartKinect();
            _sensor.ColorStream.Enable(ColorImageFormat.RgbResolution640x480Fps30);
            _sensor.DepthStream.Enable(DepthImageFormat.Resolution640x480Fps30);
            TransformSmoothParameters parameters = new TransformSmoothParameters 
            {
                Correction = 1.0f,
                JitterRadius = 0.01f,
                MaxDeviationRadius = 0.01f,
                Prediction = 1.0f,
                Smoothing = 0.9f
            };
            _sensor.SkeletonStream.Enable(parameters);
            _sensor.AllFramesReady += new EventHandler<AllFramesReadyEventArgs>(sensor_AllFramesReady);
        }

        void sensor_AllFramesReady(object sender, AllFramesReadyEventArgs e)
        {
            using (SkeletonFrame frame = e.OpenSkeletonFrame())
            {
                if (frame != null && frame.SkeletonArrayLength > 0)
                {
                    Skeleton[] skeletons = new Skeleton[frame.SkeletonArrayLength];
                    frame.CopySkeletonDataTo(skeletons);
                    var result = from p in skeletons
                                 where p.TrackingState == SkeletonTrackingState.Tracked
                                 select p;

                    _body = result.FirstOrDefault();
                    if (_body != null)
                    {
                        _gestureDetector.Add(_body.Joints[JointType.HandRight].Position, _sensor);
                    }
                }
            }
        }

        void gestureDetector_OnGestureDetected(string obj)
        {
            if (obj == MotionType.SwipeToLeft.ToString() 
                && MotionType.SwipeToLeft.ToString() == _motionType.ToString())
            {
                _trigger();
            }

            if (obj == MotionType.SwipeToRight.ToString()
                && MotionType.SwipeToRight.ToString() == _motionType.ToString())
            {
                _trigger();
            }
        }
    }
}
